﻿using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Newtonsoft.Json;
using ParamSettings;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RevitAddin
{
    [TransactionAttribute(TransactionMode.Manual)]
    [RegenerationAttribute(RegenerationOption.Manual)]
    public class drawLine : IExternalEventHandler
    {
        public void Execute(UIApplication app)
        {
            // 获取当前文档
            Document doc = app.ActiveUIDocument.Document;
            // 文件路径
            string filePath = ParamManager.getParamValue(globalVar.pathParam, globalVar.wiringResultPath, "D:\\resultPointListDicOutput.txt");
            if (!File.Exists(filePath))
            {
                TaskDialog.Show("错误", $"文件不存在：{filePath}");
                return;
            }

            // 读取文件内容并反序列化
            string fileContent = File.ReadAllText(filePath);
            Dictionary<string, Dictionary<string, List<XYZ>>> coordinatesDict;

            try
            {
                coordinatesDict =
                    JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, List<XYZ>>>>(fileContent);

            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误", $"反序列化失败：{ex.Message}");
                return;
            }


            // 获取 Revit 的短曲线容差
            double revitTolerance = doc.Application.ShortCurveTolerance;

            // 遍历 coordinatesDict 以确保所有点间距满足要求
            foreach (var outerPair in coordinatesDict.Keys.ToList()) // 使用 ToList() 创建副本，以便修改原始字典
            {
                var innerDict = coordinatesDict[outerPair];

                foreach (var innerKey in innerDict.Keys.ToList()) // 遍历内层字典的 Keys，并使用 ToList()
                {
                    List<XYZ> filteredPoints = new List<XYZ>();
                    List<XYZ> points = innerDict[innerKey];

                    // 添加第一个点
                    if (points.Count > 0)
                    {
                        filteredPoints.Add(points[0]);
                    }

                    // 过滤相邻点距离小于容差的点
                    for (int i = 1; i < points.Count; i++)
                    {
                        XYZ lastPoint = filteredPoints[filteredPoints.Count - 1];
                        XYZ currentPoint = points[i];

                        if (lastPoint.DistanceTo(currentPoint) >= revitTolerance)
                        {
                            filteredPoints.Add(currentPoint);
                        }
                    }

                    // 将过滤后的点列表替换为原始字典中的值
                    innerDict[innerKey] = filteredPoints;
                }
            }

            Global.resultDic = coordinatesDict;
            // 绘制点和线
            DrawPointsAndLines(doc, coordinatesDict);
        }
        // 绘制点和线的逻辑
        public void DrawPointsAndLines(Document doc, Dictionary<string, Dictionary<string, List<XYZ>>> coordinatesDict)
        {
            using (Transaction trans = new Transaction(doc, "Draw Points and Lines"))
            {
                trans.Start();

                foreach (var outerPair in coordinatesDict)
                {
                    var innerDict = outerPair.Value;

                    foreach (var innerPair in innerDict)
                    {
                        List<XYZ> points = innerPair.Value;

                        // 备份原始Z坐标的点列表
                        List<XYZ> originalPoints = points.Select(p => new XYZ(p.X, p.Y, p.Z)).ToList();


                        // 将所有点的 Z 坐标设置为第一个点的 Z 坐标，确保它们在同一平面上
                        //double referenceZ = points[0].Z;

                        for (int i = 0; i < points.Count; i++)
                        {
                            // 将每个点的 Z 坐标设为参考 Z 坐标
                            points[i] = new XYZ(points[i].X, points[i].Y, points[i].Z);
                        }



                        for (int i = 0; i < points.Count - 1; i++)
                        {
                            XYZ startPoint = points[i];
                            XYZ endPoint = points[i + 1];
                            // 检查线段长度
                            // double revitTolerance = doc.Application.ShortCurveTolerance;
                            // if (startPoint.DistanceTo(endPoint) < revitTolerance)
                            // {
                            //     continue; // 跳过太短的线段
                            // }
                            // // 查找满足距离要求的终点
                            // double revitTolerance = doc.Application.ShortCurveTolerance;
                            // int j = i + 1;
                            // while (j < points.Count && startPoint.DistanceTo(points[j]) < revitTolerance)
                            // {
                            //     j++; // 跳过太短的点，继续寻找
                            // }
                            //
                            // // 如果找到满足条件的点
                            // if (j < points.Count)
                            // {
                            //     endPoint = points[j];
                            // }
                            // else
                            // {
                            //     break; // 如果没有满足条件的点，退出循环
                            // }

                            // 将自定义 XYZ 转换为 Revit 的 XYZ
                            Autodesk.Revit.DB.XYZ startPointNew = startPoint.ToRevitXYZ();
                            // 将自定义 XYZ 转换为 Revit 的 XYZ
                            Autodesk.Revit.DB.XYZ endPointNew = endPoint.ToRevitXYZ();

                            Line line = null;
                            SketchPlane sketchPlane = null;
                            if (startPointNew.X == endPointNew.X && startPointNew.Y == endPointNew.Y)
                            {
                                //continue;
                                line = Line.CreateBound(startPointNew, endPointNew);
                                Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisX.ToRevitXYZ(), startPointNew);
                                sketchPlane = SketchPlane.Create(doc, plane);
                            }
                            else
                            {
                                line = Line.CreateBound(startPointNew, endPointNew);
                                Plane plane = Plane.CreateByNormalAndOrigin(
                                    XYZ.BasisZ.ToRevitXYZ().CrossProduct(startPointNew.Subtract(endPointNew)),
                                    startPointNew);
                                sketchPlane = SketchPlane.Create(doc, plane);
                            }


                            doc.Create.NewModelCurve(line, sketchPlane);


                            bool isDrawPoint = bool.Parse(ParamManager.getParamValue(globalVar.pathParam, "isDrawPoint", "false"));
                            if (isDrawPoint)
                            {
                                RevitCurve.drawFamilyInstance(new Autodesk.Revit.DB.XYZ(startPoint.X, startPoint.Y, startPoint.Z), doc, "球体");
                            }

                        }

                    }
                }

                trans.Commit();
            }
        }

        public string GetName()
        {
            return "drawLine";
        }
    }
}
